<%
putline(banner);
//--------- include
includep = ?include(projectPath+$);
includep('filesystem.tyle'); // the output of the expression is either a string with a parse error or null.
includep('db_subleme.tyle');
includep('command.tyle'   );
includep('deprecated.tyle');
includep('search.tyle'    );
includep('encryption.tyle');
includep('wikiformat.tyle');
includep('mail\mail.tyle' );

//----------only for Network Universalis:
updateDir!=() ? // only define the function upgradeServer if variable updateDir is defined
( updateDir[-1]!='\' ? (updateDir+='\';);
  upgradeServer=?
  ( putline('Busy upgrading...');
    'tyledHttp.tyle'.!(load(dbPath+$+'.def').!($!=()?(putline('Upgrading '+$2);save(updateDir+$2))););
    dirfiles(updateDir):!(load(dbPath+$+'.def').!($!=()?(putline('Upgrading '+updateDir+$2);save(updateDir+$2))););
    dirfiles(updateDir+'www'):!(load(dbPath+$+'.def').!($!=()?(putline('Upgrading ..\www\'+$2);save(updateDir+'www\'+$2))););
  );
);
reloadServer=? // no inputs or outputs
( socketMessage = ? ( quit!; include(httpPath+'tyledHttp.tyle'); socketMessage!);
);

//---------- debug
printResList = ? <[:res]> // I: $=list containing either [metaRes] or [res]
(
  putline($:!''{$->getTitle(),', '});
);
printRes = ? <[res]> // I: $=list containing either [metaRes] or [res]
(
  putline{'id:',$.id};
  putline{'name:',$->getTitle()};
  putline{'stats:',.?($.stats%!{$.key->getTitle(),$.data:!$->getTitle()})};
  putline{'metaStats:',.?($.metaStats%!{$.key->getTitle(),$.data:!$->getTitle()})};
  putline(' ');
);
printAllRes = ?
( resourceMap%!printRes($.data);
);

//--------web interface
getUser=? // I: none; O: name of user // gets the session variable 'user' and initiates all uninitialised session variables when not there
( .u=getOrPutv{"user","Guest"};
  getv("history")==()?
  ( putv{"history",&{helpRes}};
    putv{"warnings",&{}};
  );
  u
);

params2url = ? <[=>]> //O: string // converts list of parameters to URL notation
( ""($%!($.key+"="+tyleToUrl($.data)+"&")) >> 1 
);

ref = ? <link,text,class,isExtern,onClick> // O: String // creates an html link
(   '<a href="'+
    { link,
      '"',
      isExtern? ' target="_blank"',
      class!=() ? { ' class="', class, '"' },
      onClick!=() ? { ' onclick="', onClick, '"' },
      '>',
      text,
      '</a>'
    }
);

rref = ? <[=>]params,text,class,onClick> // O: String // creates an html link to resourcerer.tsp
( ref{ {'resourcerer.tsp?',params2url(params)},text,class, 0, onClick }
);

resRef =? <[res]> // O: String // creates an html link to a resource
  rref{{:"resource"=>$->getId()},getResName($)};

actref = ? <[=>]params,text,class,onClick> // O: String // creates an link to a certain subleme action
( ref{ {'action.tsp?',params2url(params)},text,class!=()?class:'action', 0, onClick}
);

pageHead=
  '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'+
  '<html xmlns="http://www.w3.org/1999/xhtml">'+
  '<head>'+
  '<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />';
blockHead='<div class="tab"><div class="tabBorder"><div class="tabBox">';
blockEnd='</div></div></div>';
resourceBlockBegin='<div class="resource"><div class="border"><div class="resourceBox"><div class="resourceInbox">';
resourceBlockEnd=blockEnd+'</div>';
blockBody=blockEnd+resourceBlockBegin;

actionForm = 'form action="action.tsp" method="get" target="_parent"'; // html string for an action form

[showStatParams={[res]res,[res]user,editable,expand,expandible,removable,header}];

showStats = ? <[stats]stats,mode,[showStatParams]params,meta>
	// *** show all statementgroups associated with the current resource, and show links to remove the complete statementgroup, or to add a new resource to a statementgroup
	// after each statementgroup-predicate, show all objects within this statementgroup, and add links to remove or to add a new object.
(
	.messageOutput={}; // catch local output
  .resName=params.res.!(@meta ? $->getMeta()->getTitle() : $->getTitle());
  .modeStr=mode +< meta;
	stats %!
	(	[descriptable=>].objs;
	  [res].pred=$.key;
		(pred.!rightsLevel(params.user)>=can.@Read) && ( objs = filterReadable{$.data, params.user} ) ?
		( %>
      <%=params.header%><%
      params.header=();%>
		  <li> <%
			mode=="" ? (%><%=resName%> <%=resRef(pred)%> <%);%>
      <font class="reslist"><%
      @objs>20 && params.expand!=-1 && params.expand!=pred.id ? (
        params.expandible=1; %>
      <%=params.editable?actref{{:"resource"=>params.res.id,'expand'=>pred.id},'...'}:'...'%><%
      ) :
			( objs:!
			  (	%>
     	  <%=$->getTitle(1)%><%params.editable?(%><font class="small"><%=actUrl{'remove'+modeStr+'Stat'+($->getMeta()==$?'Meta'),params.user,{:'resource'=>params.res.id,'p'=>pred.id,'o'=>$->getUrlId()},'X','hidden'}.!$!=()?(params.removable=1;$)%></font><%);%>, <%
			  );
			);%> <font class="small"><%=params.editable?actUrl{'add'+modeStr+'Stat',params.user,{:'resource'=>params.res.id,'p'=>pred.id},'add',(),popupActionString}%></font><%
			%></font><%
			mode!="" ? (%>&nbsp;<%=resRef(pred)%> <%=resName%><%);%>
      </li><%
		);
  );
  finishOutput(messageOutput)
); 

showMenu =? <title,menu>
(%>
<div class="menuHldr">
<ul id="nav">
<li>
	<div class="menuBorder"><div class="tabBox"><%=title%>
	</div></div>
</li><%
	menu:!
	( $[1]-={()};$[0]!=() && $[1]!={} ? 
		(%>
<li class="minor">
	<div class="menuBorder"><div class="tabBoxMinor"><%=$[0]%>
	</div></div><%
			$[1] ? (%>
	<ul><%
				$[1]:!(%>
	<li><%=$%></li><% 
				);%>
	</ul><%
			);%>
</li><%
		);
	);%>
</ul>
</div><%
);

lines2txt=? // I: list; O: string // converts a list to rows of text 
  (list2lines!.!($?($[-1]>>=1;);$));

getHtmlDiff =? <data,[:diffcmd]changes> // shows the row changes of a text 
(	.nextloc=0;
	changes:!
	{	.loc = $.loc;
	  nextloc != loc ? "...<br />",
	  nextloc += $.arg;
		$.cmd ?
		{	'<font class="removed">',
  		txt2html(''(lines2txt(data<<loc>>-$.arg))),
  		'</font>'
	  } :
		{	'<font class="added">',
  		txt2html(''(lines2txt($.arg))),
  		'</font>' 		
	  }
  }
);

getDefHistory=? <[res]res,offset,count> // shows nicely formatted list of changes to any type of resource
(	.file = historyPath(res);
	[:historyElem].elems = loadHistoryDescription{file};
  .l=@elems;
	[:historyElem].shiftedOut;
	offset==() ? ( offset = l - (l%count); );
  l>count ?
  ( %>
    <div class="header"><%
    shiftedOut=(elems<<=offset);
    elems>>=-count;
    nseq{0,(l+count-1)/count,count}:!
    ( .n=$+count-1; n>=l ? (n=l-1;);
      .t=''($+1)+( $!=n ? '...'+(n+1) );%>
      <%=$!=offset ? rref{{:"resource"=>res.id,'view'=>'history','offset'=>$},t,'action'} : t%><%
    );%>
    </div><%
  );
	(- 
    ( isBinary(res) ?
  		(	.i=0;
  			elems:!
  			{	i+=1;
  				$.time, $.editor,ref{{'download.tsp/version/',tyleToUrl(i+offset),'/resource/',tyleToUrl(res.id)},'Download','action'}
  	    }
  		) :
  		( .i=0;
  			.data={};
				shiftedOut :! processChange{&data,checkedEval(dbload{file,$.start,$.length})!};
  			elems:!
				(	.s=checkedEval(dbload{file,$.start,$.length})!; s!=() ? 
	  			{ i+=1;
	          .h=getHtmlDiff{data,s};
	    			processChange{&data,s};$.time,$.editor,
	  				{' ',ref{{'view.tsp?resource=',tyleToUrl(res->getTitle()),'&version=',tyleToUrl(i+offset)},'View','action',1},$.isDraft?' <font class="small">(minor change)</font>','<div class="content">',h,'</div>'}
	  			}
				)
  		)
    )
  ):! <time,userid,text>
  ( %>
      <div class="historyElem"><b>User:</b> <%=.?userid%>&nbsp;&nbsp;&nbsp;<b>Time:</b> <%=timeStr(time)%>
      <%=text%></div><%
  );
);

showActs=? // I: none; O: string of all actions from the recent past, visible by the current user.
( .user= getRes(getUser!); 
  .isAdmin = (getRes('Admin').!rightsLevel(user)) >=can.@Read; 
  linesplit(dbload('actlog.tyle')):! 
  ( $=checkedEval!!; 
    $!=() && ( $[0]==() ? isAdmin : ( ([res].r=getRes($[0]); $[1]+<={{resRef(r)}}; r.!rightsLevel(user)) >=can.@Read ) ) ? { $[1]:!{$[0],':',$[1],', '},$[3]!=() ? {' by: ',$[3],', '}, 'at: ',timeStr($[2]), '<br />' } 
  ) 
);

actUrl = ? <action,[res]user,[=>]params,name,class,onClick> // O: html string of an action button that is only visible if user has appropriate rights 
(	.l = params;
	l==() ? (l={:};);
	l['action']=action;
	checkAction{l,user} ?
	(	actref{l,name==()?action:name,class, onClick}
	)
);

resDef2html=? <[res]res, [res]type, [res]user, level, version>
(	type==TspResource ? 
		tsp(dbPath+defPath(res))!
	:	type==BinaryResource ?
		ref{'download.tsp/resource/'+tyleToUrl(res->getTitle())+(version!=()?'&version/'+tyleToUrl(version)),'Download','action',1}
	:
		(
			(version==()?loadDef(res):getDefVersion{res,0(version)}).!
			(
			  type == WebPageResource || type==DiscussionResource ? $
			  : type == LogResource ? logbook2html{res,$,user,level}
			  : {'<code>',txt2html!,'</code>'}
			)
		)
);

popupActionString = "return popupSelector(this);";

viewRes = ? <[res]r, [res]user, v, total,layout>
( .rn=r->getTitle();/*todo: why not id?*/
	.messageOutput={}; /* catch local output*/ %>
  <%=pageHead%>
    <link href="<%=layout%>layout.css" rel="stylesheet" type="text/css">
    <title><%=title%></title> 
  </head>
  <body><%
	total ? (%>
    <p class="statHdr"><%=title%> - Resource "<%=rref{{:'resource'=>rn},rn}%>"<%=v!=()?' version '+v%></p> 
    <div class="textBox"><%
	);	
	.lvl = r.!rightsLevel(user);
	lvl>=can.@Read ?
	(	%><%=resDef2html{r,resourceType(r),user,lvl,v}%>
		<div style="clear:both;"></div><%
		total ? (%>
   	</div><%
			[showStatParams].ssp=&{r,user,0,getp('expand'),0,0,
			  '<p class="statHdr">Meta-information:</p><ul class="stats">'};
			.expandable=&0;%>
			<%=showStats{r->getMeta().stats,"",ssp,'Meta'}%>
			<%=showStats{r->getMeta().invStats,"Inv",ssp,'Meta'}%><%
			ssp.header==() ? (%></ul><%);
			ssp.header='<p class="statHdr">Information:</p><ul class="stats">';%>
			<%=showStats{r.stats,"",ssp}%>
			<%=showStats{r.invStats,"Inv",ssp}%><%
			ssp.header==() ? (%></ul><%);
    )
	)
	: (%><%="No permission"%><%);%>
  </body>
  </html><%
	finishOutput(messageOutput)
);

zipResources=? <[res=>]resourceSet,[res]user>
( .file=tempPath+user->getTitle()+'.zip';
  mkdir{tempPath,'zip'};

  mkdir{tempPath,'zip\binaries'};
	sys(cmd{'del /s /q "',tempPath,'zip','"' });
	sys(cmd{'del "',file,'"' });
	load(wwwPath+'\genlayout.css').!save(tempPath+'zip\genlayout.css');
  resourceSet:!
  ( ( viewRes{$,user,(),-1,1,'gen'}.!
      RE_onMatch{`"/?resourcerer\.tsp\?resource=([^&"]**)`,?
				{'"',StringToTyle($2[0]).! ( @@$==@@0 ? getRes!->getTitle() : replace{'+',' '} ), '.html'
				}
			}.!
			RE_onMatch{`"/?download.tsp[?/]resource[=/]([^&"]**)`,?
				{'"binaries\',$2[0].!replace{'+',' '}
				}
			}
    ).!save(tempPath+'zip\'+$2->getTitle()+'.html');
		sleep();
    isBinary! ?
    ( loadDef! .! save(tempPath+'zip\binaries\'+$2->getTitle());
			sleep();
    )
  );
	sys(cmd{'cd /d "',tempPath,'" && "',projectPath, 'zip\zip.exe" -r "', file,'" zip'});
);

loadZip = ? load{{tempPath,$,'.zip'}};

initLayout= ?
(   messageOutput={};
    tsp(projectPath+'layout.css.tsp')!;
    -messageOutput.!save(projectPath+'www\genlayout.css');
    messageOutput = {};
);

//------------- { implementations of functions that are called by tyledHttp.tyle
quitProject = ? ( storeDatabase!; Search.quit!; ); // quit subleme
serializeVariables = ? <[session]> // O: all data that should be stored on disk when leaving subleme
( {: "user" } @ $.variables
);
unserializeVariables = ? <[session]> // I: session in which the element 'variable' contains data loaded from disk; O: variables
// converts the loaded data into
( $.variables 
);

useHTTPS=1;

initProject=?
(
  initDatabase!;
  Search.init!;
  initCountDown!;
  initLayout!;
  showLog!; //everything is initialised: now show log file to user.
);
//-------------- }

%>
